/**
 * @author:albert
 * @date:2016年6月6日
 */
package com.bkbw.live.battle.business.behaviors;

import com.badlogic.gdx.math.Bezier;
import com.badlogic.gdx.math.Vector2;

/**
 * @author albert
 *
 */
public class BezierMove {
	
	public static int Angle30 = 30;
	public static int Angle60 = 60;
	
	
	private Vector2 start = new Vector2();
	private Vector2 end = new Vector2();
	private int angle;
	private float radians;
	private Bezier<Vector2> bezier;
	private Vector2 controlVector = new Vector2();
	private float speedLen;
	private float bezierLen;
	private float currentLen;
	
	public BezierMove(Vector2 start, Vector2 end, int angle, float speedLen) {
		reset(start, end, angle, speedLen);
	}
	
	// 根据起始位置，结束为止，起始角度，初始化贝塞尔曲线。
	// 并且保存移动速度的标量，以后速度*deltaTime就得到了每次沿着贝塞尔曲线移动的距离
	// 采用point=3的插值算法，即，p0，p1，p2，其中p0是起始为止，p2是结束为止，而p1就是控制点
	// p1的条件，（p0，p1）是与（p0，p2）向量角度为angle的向量，p1在（p0，p2）线段的垂直投影在（p0，p2）线段的中间
	// 根据条件，能计算出p1的位置，沿着（p0，p2）旋转指定角度，再把向量标准化，再乘以长度，得到控制点向量，还需要加上p0，回到坐标系
	public void reset(Vector2 start, Vector2 end, int angle, float speedLen) {
		this.start.set(start);
		this.end.set(end);
		Vector2 sub = new Vector2();
		radians = angle * 0.01745329F;
		System.out.println("radians " + radians);
		this.speedLen = speedLen;
		// (|p0,p2|/2) / |p0,p1| = cos(rad)  --> |p0,p1| = (|p0,p2|/2)/cos(rad)
		float controlVectorLen = sub.set(this.end).sub(this.start).len() / 2 / (float)Math.cos(radians);
		
		controlVector.set(this.end).sub(this.start).rotateRad(radians).nor().scl(controlVectorLen).add(this.start);
		System.out.println("controlVector " + controlVector);
		
		Vector2[] va = new Vector2[3];
		va[0] = new Vector2(this.start);
		va[1] = new Vector2(this.controlVector);
		va[2] = new Vector2(this.end);
		bezier = new Bezier<Vector2>(va);
		bezierLen = bezier.approxLength(5);
	}
	
	public void getFirst(Vector2 pos, Vector2 derivate) {
		bezier.valueAt(pos, 0.0f);
		bezier.derivativeAt(derivate, 0.0f);
	}
	
	public boolean move(float dt, Vector2 pos, Vector2 derivate) {
		boolean moveEnd = false;
		float movement = dt * speedLen;
		currentLen += movement;
		if (currentLen >= bezierLen) {
			currentLen = bezierLen;
			moveEnd = true;
		}
		float t = currentLen / bezierLen;
		bezier.valueAt(pos, t);
		bezier.derivativeAt(derivate, t);
		return moveEnd;
	}
	
	public void changeSpeed(int speedLen) {
		this.speedLen = speedLen;
	}
	
	public float getRate() {
		return currentLen / bezierLen;
	}
}
